using jiuyuan.数据.基础数据类;
using jiuyuan.数据.怪物类;
using jiuyuan.数据.玩家类;
using jiuyuan.服务;
using jiuyuan.管理器;
using Microsoft.AspNetCore.SignalR;
using System.Collections.Concurrent;

namespace jiuyuan.Hubs;

// 在线玩家信息
public class 在线玩家
{
    public string 连接ID { get; set; } = "";
    public string 玩家名称 { get; set; } = "";
    public string 当前位置 { get; set; } = "";
    public DateTime 登录时间 { get; set; } = DateTime.Now;
    public Guid? 玩家角色Id { get; set; }
    public string 小队ID { get; set; } = "";
    // 添加战斗相关字段
    public Guid? 当前战斗Id { get; set; }
    public bool 是否自动战斗 { get; set; }
    public DateTime 最后活动时间 { get; set; } = DateTime.Now;
    public bool 是否准备就绪 { get; set; } = false; // 添加准备状态
}

// 聊天消息类
public class 聊天消息
{
    public string 发送者 { get; set; } = "";
    public string 消息内容 { get; set; } = "";
    public string 频道 { get; set; } = "";
    public DateTime 时间戳 { get; set; } = DateTime.Now;
    public string 消息类型 { get; set; } = "normal"; // normal, system, warning, etc.
}

// 管理员通知类
public class 管理员通知
{
    public string 标题 { get; set; } = "";
    public string 内容 { get; set; } = "";
    public DateTime 时间戳 { get; set; } = DateTime.Now;
    public string 类型 { get; set; } = "通知";
    public string 优先级 { get; set; } = "normal"; // low, normal, high, urgent
}

// 玩家决策数据
public class 玩家决策数据
{
    public Guid 玩家Id { get; set; }
    public Guid 战斗Id { get; set; }
    public string 技能名称 { get; set; } = "";
    public List<Guid> 目标ID列表 { get; set; } = new();
    public DateTime 提交时间 { get; set; } = DateTime.Now;
    public int 决策时间 { get; set; } = 0; // 决策耗时（毫秒）
}

// 玩家战斗状态
public class 玩家战斗状态
{
    public Guid 玩家Id { get; set; }
    public Guid 战斗Id { get; set; }
    public bool 是否自动战斗 { get; set; }
    public DateTime 更新时间 { get; set; } = DateTime.Now;
    public bool 是否准备就绪 { get; set; } = false; // 添加准备状态
}

// 战斗消息
public class 战斗消息
{
    public Guid 战斗Id { get; set; }
    public string 消息内容 { get; set; } = "";
    public string 消息类型 { get; set; } = "log"; // log, state, turn, result, system
    public DateTime 时间戳 { get; set; } = DateTime.Now;
    public string 发送者 { get; set; } = "系统";
}

// 战斗状态更新
public class 战斗状态更新
{
    public Guid 战斗Id { get; set; }
    public Guid 单位Id { get; set; }
    public int 当前生命值 { get; set; }
    public int 当前魔法值 { get; set; }
    public int 最大生命值 { get; set; }
    public int 最大魔法值 { get; set; }
    public bool 是否存活 { get; set; } = true;
    public DateTime 更新时间 { get; set; } = DateTime.Now;
}

// 回合信息
public class 回合信息
{
    public Guid 战斗Id { get; set; }
    public Guid 当前行动单位Id { get; set; }
    public string 单位类型 { get; set; } = "player"; // "player" 或 "monster"
    public string 单位名称 { get; set; } = "";
    public int 剩余时间 { get; set; } = 30; // 回合剩余时间
    public DateTime 回合开始时间 { get; set; } = DateTime.Now;
    public int 回合数 { get; set; } = 1; // 添加回合数
}

// 战斗信息
public class 战斗信息
{
    public Guid 战斗Id { get; set; }
    public string 副本名称 { get; set; } = "";
    public List<Guid> 玩家列表 { get; set; } = new();
    public List<Guid> 怪物列表 { get; set; } = new();
    public string 战斗状态 { get; set; } = "active"; // active, victory, defeat, fled
    public DateTime 开始时间 { get; set; } = DateTime.Now;
    public DateTime? 结束时间 { get; set; }
    
    // 添加玩家队伍和怪物队伍属性
    public List<玩家> 玩家队伍 { get; set; } = new();
    public List<怪物> 怪物队伍 { get; set; } = new();
    
    // 添加回合信息
    public int 当前回合数 { get; set; } = 1;
    public Guid? 当前行动单位Id { get; set; }
    public int 回合剩余时间 { get; set; } = 30;
}

// 回合计时器
public class 回合计时器(聊天Hub hub, Guid 战斗Id, int 初始时间, ConcurrentDictionary<Guid, List<string>> 战斗观察者列表)
{
    private System.Timers.Timer? _计时器;

    public void 启动()
    {
        _计时器 = new System.Timers.Timer(1000); // 每秒触发一次
        _计时器.Elapsed += async (sender, e) => await 计时器触发();
        _计时器.Start();
    }

    private async Task 计时器触发()
    {
        初始时间--;
        
        // 通知所有观察者剩余时间
        if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
        {
            await hub.Clients.Clients(观察者).SendAsync("更新回合时间", 战斗Id, 初始时间);
        }

        // 如果时间用完，自动提交默认决策
        if (初始时间 <= 0)
        {
            await hub.自动提交决策(战斗Id);
            停止();
        }
    }

    public void 停止()
    {
        _计时器?.Stop();
        _计时器?.Dispose();
    }

    public void 重置(int 新时间)
    {
        初始时间 = 新时间;
    }
}

public class 聊天Hub(游戏主服务 游戏主服务, 副本管理器 副本管理器,
              怪物AI管理器 怪物AI管理器, 战斗管理器 战斗管理器,
              ILogger<聊天Hub> 日志器) : Hub
{
    // 存储在线玩家信息的静态集合
    private static readonly ConcurrentDictionary<string, 在线玩家> 在线玩家列表 = new();

    // 存储小队信息
    private static readonly ConcurrentDictionary<string, List<string>> 小队成员列表 = new();

    // 存储战斗相关信息
    private static readonly ConcurrentDictionary<Guid, List<string>> 战斗观察者列表 = new();
    private static readonly ConcurrentDictionary<Guid, 战斗信息> 战斗信息列表 = new();
    private static readonly ConcurrentDictionary<Guid, 玩家战斗状态> 玩家战斗状态列表 = new();
    private static readonly ConcurrentDictionary<Guid, 玩家决策数据> 玩家决策缓存 = new();
    private static readonly ConcurrentDictionary<Guid, 回合计时器> 回合计时器列表 = new(); // 添加回合计时器
    private readonly 战斗管理器 _战斗管理器 = 战斗管理器;

    #region 连接管理
    // 连接建立时
    public override async Task OnConnectedAsync()
    {
        日志器.LogInformation("客户端连接: {ConnectionId}", Context.ConnectionId);

        // 发送连接成功消息
        await Clients.Caller.SendAsync("连接成功", Context.ConnectionId);

        await base.OnConnectedAsync();
    }

    // 玩家登录
    public async Task 玩家登录(string 玩家名称, Guid? 玩家角色Id = null, string 当前位置 = "未知")
    {
        try
        {
            // 验证玩家名称
            if (string.IsNullOrWhiteSpace(玩家名称))
            {
                await Clients.Caller.SendAsync("登录失败", "玩家名称不能为空");
                return;
            }

            var 在线玩家 = new 在线玩家
            {
                连接ID = Context.ConnectionId,
                玩家名称 = 玩家名称.Trim(),
                玩家角色Id = 玩家角色Id,
                当前位置 = 当前位置,
                登录时间 = DateTime.Now,
                最后活动时间 = DateTime.Now
            };

            // 检查是否已经登录
            var 已存在连接 = 在线玩家列表.Values.FirstOrDefault(p =>
                p.玩家名称 == 玩家名称 && p.连接ID != Context.ConnectionId);

            if (已存在连接 != null)
            {
                // 踢掉之前的连接
                await Clients.Client(已存在连接.连接ID).SendAsync("被踢下线", "账号在其他地方登录");
                在线玩家列表.TryRemove(已存在连接.连接ID, out _);
            }

            在线玩家列表[Context.ConnectionId] = 在线玩家;

            // 加入世界组
            await Groups.AddToGroupAsync(Context.ConnectionId, "世界频道");

            // 通知客户端登录成功
            await Clients.Caller.SendAsync("登录成功", 玩家名称, Context.ConnectionId);

            // 通知其他玩家
            await Clients.OthersInGroup("世界频道").SendAsync("玩家加入", 玩家名称, 当前位置);

            // 发送当前在线玩家列表
            await 发送在线玩家列表();

            日志器.LogInformation("玩家 {玩家名称} 登录成功", 玩家名称);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "玩家登录时发生错误");
            await Clients.Caller.SendAsync("登录失败", "登录时发生错误");
        }
    }

    // 心跳检测
    public async Task 心跳()
    {
        if (在线玩家列表.TryGetValue(Context.ConnectionId, out var 玩家))
        {
            玩家.最后活动时间 = DateTime.Now;
            在线玩家列表[Context.ConnectionId] = 玩家;
        }
        await Clients.Caller.SendAsync("心跳响应", DateTime.Now);
    }

    // 玩家断开连接时的处理
    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        try
        {
            if (在线玩家列表.TryRemove(Context.ConnectionId, out var 玩家))
            {
                // 离开所有战斗
                if (玩家.当前战斗Id.HasValue)
                {
                    await 离开战斗观察(玩家.当前战斗Id.Value);
                }

                // 离开小队
                if (!string.IsNullOrEmpty(玩家.小队ID))
                {
                    await 离开小队(玩家.小队ID);
                }

                // 离开世界频道
                await Groups.RemoveFromGroupAsync(Context.ConnectionId, "世界频道");

                // 通知其他玩家
                await Clients.Others.SendAsync("玩家离开", 玩家.玩家名称);

                日志器.LogInformation("玩家 {玩家名称} 断开连接", 玩家.玩家名称);
            }

            await base.OnDisconnectedAsync(exception);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "处理断开连接时发生错误");
        }
    }
    #endregion

    #region 聊天功能
    // 发送世界消息
    public async Task 发送世界消息(string 用户名, string 消息)
    {
        try
        {
            if (string.IsNullOrEmpty(消息) || 消息.Length > 500)
            {
                await Clients.Caller.SendAsync("消息发送失败", "消息长度不符合要求");
                return;
            }

            // 验证发送者
            if (!在线玩家列表.ContainsKey(Context.ConnectionId))
            {
                await Clients.Caller.SendAsync("消息发送失败", "请先登录");
                return;
            }

            var 聊天消息 = new 聊天消息
            {
                发送者 = 用户名,
                消息内容 = 消息,
                频道 = "world",
                时间戳 = DateTime.Now
            };

            // 广播给所有客户端
            await Clients.All.SendAsync("接收世界消息", 用户名, 消息, DateTime.Now);

            日志器.LogDebug("世界消息: {用户名} - {消息}", 用户名, 消息);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "发送世界消息时发生错误");
            await Clients.Caller.SendAsync("消息发送失败", "发送消息时发生错误");
        }
    }

    // 发送小队消息
    public async Task 发送小队消息(string 小队ID, string 用户名, string 消息)
    {
        try
        {
            if (string.IsNullOrEmpty(消息) || 消息.Length > 500)
            {
                await Clients.Caller.SendAsync("消息发送失败", "消息长度不符合要求");
                return;
            }

            // 验证玩家是否在小队中
            if (string.IsNullOrEmpty(小队ID) || !在线玩家列表.ContainsKey(Context.ConnectionId))
            {
                await Clients.Caller.SendAsync("消息发送失败", "未加入小队或未登录");
                return;
            }

            var 玩家 = 在线玩家列表[Context.ConnectionId];
            if (玩家.小队ID != 小队ID)
            {
                await Clients.Caller.SendAsync("接收小队消息", "系统", "你不在这个小队中");
                return;
            }

            var 聊天消息 = new 聊天消息
            {
                发送者 = 用户名,
                消息内容 = 消息,
                频道 = "party",
                时间戳 = DateTime.Now
            };

            // 广播给指定小队的所有成员
            await Clients.Group($"小队_{小队ID}").SendAsync("接收小队消息", 用户名, 消息, DateTime.Now);

            日志器.LogDebug("小队消息: {小队ID} - {用户名} - {消息}", 小队ID, 用户名, 消息);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "发送小队消息时发生错误");
            await Clients.Caller.SendAsync("消息发送失败", "发送消息时发生错误");
        }
    }

    // 发送私聊消息
    public async Task 发送私聊消息(string 接收者名称, string 用户名, string 消息)
    {
        try
        {
            if (string.IsNullOrEmpty(消息) || 消息.Length > 500)
            {
                await Clients.Caller.SendAsync("消息发送失败", "消息长度不符合要求");
                return;
            }

            // 检查是否是发送给测试机器人
            if (接收者名称 == "测试机器人")
            {
                await Clients.Caller.SendAsync("接收私聊消息", 用户名, 消息, DateTime.Now);

                // 模拟机器人回复
                await Task.Delay(1000);
                var 回复消息 = $"你好，{用户名}！我是测试机器人。你刚才说: \"{消息}\"";
                await Clients.Caller.SendAsync("接收私聊消息", "测试机器人", 回复消息, DateTime.Now);
                return;
            }

            // 查找接收者连接ID
            var 接收者 = 在线玩家列表.Values.FirstOrDefault(p => p.玩家名称 == 接收者名称);
            if (接收者 == null)
            {
                await Clients.Caller.SendAsync("接收私聊消息", "系统", "玩家不在线", DateTime.Now);
                return;
            }

            var 聊天消息 = new 聊天消息
            {
                发送者 = 用户名,
                消息内容 = 消息,
                频道 = "private",
                时间戳 = DateTime.Now
            };

            // 发送给接收者
            await Clients.Client(接收者.连接ID).SendAsync("接收私聊消息", 用户名, 消息, DateTime.Now);

            // 同时发送给自己
            await Clients.Caller.SendAsync("接收私聊消息", 用户名, 消息, DateTime.Now);

            日志器.LogDebug("私聊消息: {发送者} -> {接收者} - {消息}", 用户名, 接收者名称, 消息);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "发送私聊消息时发生错误");
            await Clients.Caller.SendAsync("消息发送失败", "发送消息时发生错误");
        }
    }
    #endregion

    #region 小队管理
    // 创建小队
    public async Task 创建小队()
    {
        try
        {
            // 生成唯一小队ID
            var 小队ID = Guid.NewGuid().ToString("N")[..8];

            // 加入小队
            await 加入小队(小队ID);

            日志器.LogInformation("玩家 {ConnectionId} 创建小队 {小队ID}", Context.ConnectionId, 小队ID);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "创建小队时发生错误");
            await Clients.Caller.SendAsync("小队创建失败", "创建小队时发生错误");
        }
    }

    // 加入小队
    public async Task 加入小队(string 小队ID)
    {
        try
        {
            if (string.IsNullOrEmpty(小队ID))
            {
                await Clients.Caller.SendAsync("小队加入失败", "小队ID不能为空");
                return;
            }

            // 更新玩家信息
            if (在线玩家列表.TryGetValue(Context.ConnectionId, out var 玩家))
            {
                玩家.小队ID = 小队ID;
                在线玩家列表[Context.ConnectionId] = 玩家;
            }

            // 添加到小队组
            await Groups.AddToGroupAsync(Context.ConnectionId, $"小队_{小队ID}");

            // 更新小队成员列表
            小队成员列表.AddOrUpdate(
                小队ID,
                new List<string> { Context.ConnectionId },
                (key, existingList) =>
                {
                    if (!existingList.Contains(Context.ConnectionId))
                    {
                        existingList.Add(Context.ConnectionId);
                    }
                    return existingList;
                }
            );

            await Clients.Caller.SendAsync("小队加入成功", 小队ID);
            await Clients.Group($"小队_{小队ID}").SendAsync("小队成员更新", 获取小队成员信息(小队ID));

            日志器.LogInformation("玩家 {玩家名称} 加入小队 {小队ID}", 玩家?.玩家名称, 小队ID);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "加入小队时发生错误");
            await Clients.Caller.SendAsync("小队加入失败", "加入小队时发生错误");
        }
    }

    // 离开小队
    public async Task 离开小队(string 小队ID)
    {
        try
        {
            if (string.IsNullOrEmpty(小队ID))
            {
                return;
            }

            // 更新玩家信息
            if (在线玩家列表.TryGetValue(Context.ConnectionId, out var 玩家))
            {
                玩家.小队ID = "";
                在线玩家列表[Context.ConnectionId] = 玩家;
            }

            // 从小队组移除
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"小队_{小队ID}");

            // 更新小队成员列表
            if (小队成员列表.TryGetValue(小队ID, out var 成员列表))
            {
                成员列表.Remove(Context.ConnectionId);
                if (成员列表.Count == 0)
                {
                    小队成员列表.TryRemove(小队ID, out _);
                }
                else
                {
                    await Clients.Group($"小队_{小队ID}").SendAsync("小队成员更新", 获取小队成员信息(小队ID));
                }
            }

            await Clients.Caller.SendAsync("小队离开成功", 小队ID);

            日志器.LogInformation("玩家 {玩家名称} 离开小队 {小队ID}", 玩家?.玩家名称, 小队ID);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "离开小队时发生错误");
            await Clients.Caller.SendAsync("小队离开失败", "离开小队时发生错误");
        }
    }

    // 获取在线玩家列表
    public async Task 获取在线玩家列表()
    {
        try
        {
            var 在线玩家 = 在线玩家列表.Values.ToList();
            await Clients.Caller.SendAsync("接收在线玩家列表", 在线玩家);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "获取在线玩家列表时发生错误");
        }
    }
    #endregion

    #region 战斗系统
    // 创建战斗
    public async Task<Guid> 创建战斗(string 副本名称, List<Guid> 玩家列表, List<Guid> 怪物列表)
    {
        try
        {
            var 战斗Id = Guid.NewGuid();
            var 战斗信息 = new 战斗信息
            {
                战斗Id = 战斗Id,
                副本名称 = 副本名称,
                玩家列表 = 玩家列表,
                怪物列表 = 怪物列表,
                开始时间 = DateTime.Now
            };

            战斗信息列表[战斗Id] = 战斗信息;

            // 初始化战斗观察者列表
            战斗观察者列表[战斗Id] = [];

            日志器.LogInformation("创建战斗: {战斗Id} - {副本名称}", 战斗Id, 副本名称);

            return 战斗Id;
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "创建战斗时发生错误");
            throw;
        }
    }

    // 加入战斗观察
    public async Task 加入战斗观察(Guid 战斗Id)
    {
        try
        {
            战斗观察者列表.AddOrUpdate(战斗Id,
                [Context.ConnectionId],
                (key, existingList) =>
                {
                    if (!existingList.Contains(Context.ConnectionId))
                    {
                        existingList.Add(Context.ConnectionId);
                    }
                    return existingList;
                });

            await Groups.AddToGroupAsync(Context.ConnectionId, $"战斗_{战斗Id}");

            // 更新玩家当前战斗状态
            if (在线玩家列表.TryGetValue(Context.ConnectionId, out var 玩家))
            {
                玩家.当前战斗Id = 战斗Id;
                在线玩家列表[Context.ConnectionId] = 玩家;
            }

            await Clients.Caller.SendAsync("加入战斗观察成功", 战斗Id);

            日志器.LogInformation("客户端 {ConnectionId} 加入战斗观察: {战斗Id}", Context.ConnectionId, 战斗Id);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "加入战斗观察时发生错误");
            await Clients.Caller.SendAsync("加入战斗观察失败", "加入战斗观察时发生错误");
        }
    }

    // 离开战斗观察
    public async Task 离开战斗观察(Guid 战斗Id)
    {
        try
        {
            if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
            {
                观察者.Remove(Context.ConnectionId);
                if (观察者.Count == 0)
                {
                    战斗观察者列表.TryRemove(战斗Id, out _);
                }
            }

            await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"战斗_{战斗Id}");

            // 更新玩家当前战斗状态
            if (在线玩家列表.TryGetValue(Context.ConnectionId, out var 玩家))
            {
                玩家.当前战斗Id = null;
                在线玩家列表[Context.ConnectionId] = 玩家;
            }

            await Clients.Caller.SendAsync("离开战斗观察成功", 战斗Id);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "离开战斗观察时发生错误");
        }
    }

    // 通知战斗开始
    public async Task 通知战斗开始(Guid 战斗Id, string 副本名称, List<Guid> 玩家列表, List<Guid> 怪物列表)
    {
        try
        {
            // 将参与战斗的玩家加入战斗组
            foreach (var 玩家Id in 玩家列表)
            {
                var 连接ID = 获取玩家连接ID(玩家Id);
                if (连接ID != null)
                {
                    await 加入战斗观察(战斗Id);
                }
            }

            var 战斗开始消息 = $"战斗开始! 地点: {副本名称}";
            await 发送战斗日志(战斗Id, 战斗开始消息, "battle-start");

            // 通知所有观察者战斗开始
            if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
            {
                await Clients.Clients(观察者).SendAsync("战斗开始", 战斗Id, 副本名称);
            }

            日志器.LogInformation("战斗 {战斗Id} 开始: {副本名称}", 战斗Id, 副本名称);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "通知战斗开始时发生错误");
        }
    }

    // 发送战斗日志
    public async Task 发送战斗日志(Guid 战斗Id, string 日志内容, string 消息类型 = "log", string 发送者 = "系统")
    {
        try
        {
            var 战斗消息 = new 战斗消息
            {
                战斗Id = 战斗Id,
                消息内容 = 日志内容,
                消息类型 = 消息类型,
                时间戳 = DateTime.Now,
                发送者 = 发送者
            };

            // 发送给战斗观察者
            if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
            {
                await Clients.Clients(观察者).SendAsync("接收战斗日志", 日志内容);
            }

            日志器.LogDebug("战斗日志: {战斗Id} - {日志内容}", 战斗Id, 日志内容);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "发送战斗日志时发生错误");
        }
    }

    // 更新战斗单位状态
    public async Task 更新战斗单位状态(Guid 战斗Id, Guid 单位Id, int 当前生命值, int 当前魔法值, int 最大生命值, int 最大魔法值, bool 是否存活 = true)
    {
        try
        {
            var 状态更新 = new 战斗状态更新
            {
                战斗Id = 战斗Id,
                单位Id = 单位Id,
                当前生命值 = 当前生命值,
                当前魔法值 = 当前魔法值,
                最大生命值 = 最大生命值,
                最大魔法值 = 最大魔法值,
                是否存活 = 是否存活,
                更新时间 = DateTime.Now
            };

            if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
            {
                await Clients.Clients(观察者).SendAsync("更新单位状态", 单位Id, 当前生命值, 当前魔法值, 是否存活);
            }

            日志器.LogDebug("更新单位状态: {战斗Id} - {单位Id} - HP:{当前生命值}/{最大生命值} MP:{当前魔法值}/{最大魔法值}",
                战斗Id, 单位Id, 当前生命值, 最大生命值, 当前魔法值, 最大魔法值);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "更新战斗单位状态时发生错误");
        }
    }

    // 设置当前回合
    public async Task 设置当前回合(Guid 战斗Id, Guid 单位Id, string 单位类型 = "player", string 单位名称 = "", int 剩余时间 = 30)
    {
        try
        {
            var 回合信息 = new 回合信息
            {
                战斗Id = 战斗Id,
                当前行动单位Id = 单位Id,
                单位类型 = 单位类型,
                单位名称 = 单位名称,
                剩余时间 = 剩余时间,
                回合开始时间 = DateTime.Now
            };

            if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
            {
                await Clients.Clients(观察者).SendAsync("设置当前行动玩家", 单位Id);

                if (单位类型 == "player")
                {
                    var 玩家连接ID = 获取玩家连接ID(单位Id);
                    if (玩家连接ID != null)
                    {
                        await Clients.Client(玩家连接ID).SendAsync("玩家回合开始", 单位Id, 剩余时间);
                    }
                }
            }

            日志器.LogDebug("设置当前回合: {战斗Id} - {单位Id} - {单位类型} - 剩余时间:{剩余时间}",
                战斗Id, 单位Id, 单位类型, 剩余时间);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "设置当前回合时发生错误");
        }
    }

    // 玩家提交战斗决策（带时间限制）
    public async Task 提交战斗决策(Guid 战斗Id, Guid 玩家Id, string 技能名称, List<Guid> 目标ID列表)
    {
        try
        {
            日志器.LogInformation("玩家 {玩家Id} 提交战斗决策: 战斗={战斗Id}, 技能={技能名称}, 目标数={目标数}",
                玩家Id, 战斗Id, 技能名称, 目标ID列表.Count);

            // 验证玩家是否在战斗中
            if (!验证玩家在战斗中(玩家Id, 战斗Id))
            {
                await Clients.Caller.SendAsync("战斗决策错误", "玩家不在战斗中");
                return;
            }

            // 验证战斗是否存在
            if (!战斗信息列表.ContainsKey(战斗Id))
            {
                await Clients.Caller.SendAsync("战斗决策错误", "战斗不存在");
                return;
            }

            // 记录决策时间
            var 决策开始时间 = DateTime.Now;

            // 缓存玩家决策
            var 决策数据 = new 玩家决策数据
            {
                玩家Id = 玩家Id,
                战斗Id = 战斗Id,
                技能名称 = 技能名称,
                目标ID列表 = 目标ID列表,
                提交时间 = DateTime.Now,
                决策时间 = (int)(DateTime.Now - 决策开始时间).TotalMilliseconds
            };

            玩家决策缓存[玩家Id] = 决策数据;

            // 调用战斗管理器处理玩家决策
            var 决策 = new AI决策("技能", 技能名称, null)
            {
                目标列表 = 目标ID列表.Select(id => 获取战斗单位(战斗Id, id)).Where(u => u != null).ToList()!,
                提交时间 = DateTime.Now
            };
            
            _战斗管理器.处理玩家决策(玩家Id, 决策);
            var 结果 = jiuyuan.管理器.操作结果.成功("决策已接受");

            if (结果.是否成功)
            {
                await Clients.Caller.SendAsync("战斗决策接受", "决策已接受");

                // 发送战斗日志
                await 发送战斗日志(战斗Id, $"[{获取玩家名称(玩家Id)}] 使用了 [{技能名称}]", "player-action", 获取玩家名称(玩家Id));

                // 停止当前回合计时器
                if (回合计时器列表.TryGetValue(战斗Id, out var 计时器))
                {
                    计时器.停止();
                    回合计时器列表.TryRemove(战斗Id, out _);
                }

                日志器.LogInformation("玩家 {玩家Id} 决策处理成功，耗时 {耗时}ms", 玩家Id, 决策数据.决策时间);
            }
            else
            {
                await Clients.Caller.SendAsync("战斗决策错误", 结果.消息);
                日志器.LogWarning("玩家 {玩家Id} 决策处理失败: {错误消息}", 玩家Id, 结果.消息);
            }
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "提交战斗决策时发生错误");
            await Clients.Caller.SendAsync("战斗决策错误", "提交决策时发生错误");
        }
    }

    // 自动提交决策（超时处理）
    public async Task 自动提交决策(Guid 战斗Id)
    {
        try
        {
            // 获取当前战斗信息
            if (!战斗信息列表.TryGetValue(战斗Id, out var 战斗信息))
                return;

            // 为未提交决策的玩家自动生成AI决策
            foreach (var 玩家Id in 战斗信息.玩家列表)
            {
                // 检查玩家是否已提交决策
                if (!玩家决策缓存.ContainsKey(玩家Id))
                {
                    // 生成AI决策
                    var 玩家 = 战斗信息.玩家队伍.FirstOrDefault(p => p.Id == 玩家Id);
                    if (玩家 != null)
                    {
                        var AI决策 = 怪物AI管理器.生成玩家决策(玩家, [.. 战斗信息.怪物队伍.Cast<怪物>()]);
                        
                        // 提交AI决策
                        var 决策数据 = new 玩家决策数据
                        {
                            玩家Id = 玩家Id,
                            战斗Id = 战斗Id,
                            技能名称 = AI决策.技能名称 ?? "攻击",
                            目标ID列表 = AI决策.目标列表.Select(t => t.Id).ToList(),
                            提交时间 = DateTime.Now,
                            决策时间 = -1 // 表示超时自动决策
                        };

                        玩家决策缓存[玩家Id] = 决策数据;

                        // 发送超时通知
                        var 玩家连接ID = 获取玩家连接ID(玩家Id);
                        if (玩家连接ID != null)
                        {
                            await Clients.Client(玩家连接ID).SendAsync("战斗决策超时", "由于超时，系统已为您自动选择行动");
                        }

                        日志器.LogInformation("玩家 {玩家Id} 决策超时，已自动提交AI决策", 玩家Id);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "自动提交决策时发生错误");
        }
    }

    // 启动回合计时器
    public async Task 启动回合计时器(Guid 战斗Id, int 时间限制 = 30)
    {
        try
        {
            // 创建并启动回合计时器
            var 计时器 = new 回合计时器(this, 战斗Id, 时间限制,战斗观察者列表);
            计时器.启动();
            
            回合计时器列表[战斗Id] = 计时器;

            // 通知所有观察者
            if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
            {
                await Clients.Clients(观察者).SendAsync("回合计时器启动", 战斗Id, 时间限制);
            }

            日志器.LogInformation("战斗 {战斗Id} 回合计时器已启动，时间限制: {时间限制}秒", 战斗Id, 时间限制);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "启动回合计时器时发生错误");
        }
    }

    // 更新战斗状态（同步机制）
    public async Task 更新战斗状态(Guid 战斗Id, 战斗信息 战斗信息)
    {
        try
        {
            // 更新本地战斗信息
            战斗信息列表[战斗Id] = 战斗信息;

            // 同步给所有观察者
            if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
            {
                await Clients.Clients(观察者).SendAsync("战斗状态更新", 战斗信息);
            }

            日志器.LogDebug("战斗 {战斗Id} 状态已更新并同步给 {观察者数量} 个观察者", 战斗Id, 观察者?.Count ?? 0);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "更新战斗状态时发生错误");
        }
    }

    // 发送战斗同步数据
    public async Task 发送战斗同步数据(Guid 战斗Id)
    {
        try
        {
            if (战斗信息列表.TryGetValue(战斗Id, out var 战斗信息))
            {
                // 发送给所有观察者
                if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
                {
                    await Clients.Clients(观察者).SendAsync("战斗同步数据", 战斗信息);
                }
            }
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "发送战斗同步数据时发生错误");
        }
    }

    // 设置自动战斗
    public async Task 设置自动战斗(Guid 战斗Id, Guid 玩家Id, bool 是否自动战斗)
    {
        try
        {
            // 更新玩家状态
            var 玩家连接ID = 获取玩家连接ID(玩家Id);
            if (玩家连接ID != null && 在线玩家列表.TryGetValue(玩家连接ID, out var 玩家))
            {
                玩家.是否自动战斗 = 是否自动战斗;
                在线玩家列表[玩家连接ID] = 玩家;
            }

            // 更新战斗状态
            var 战斗状态 = new 玩家战斗状态
            {
                玩家Id = 玩家Id,
                战斗Id = 战斗Id,
                是否自动战斗 = 是否自动战斗,
                更新时间 = DateTime.Now
            };
            玩家战斗状态列表[玩家Id] = 战斗状态;

            //await _战斗管理器.设置玩家自动战斗(战斗Id, 玩家Id, 是否自动战斗);
            await Clients.Caller.SendAsync("自动战斗设置", 是否自动战斗);

            // 发送系统消息
            await 发送战斗日志(战斗Id, $"[{获取玩家名称(玩家Id)}] 自动战斗{(是否自动战斗 ? "开启" : "关闭")}", "system");

            日志器.LogInformation("玩家 {玩家Id} 自动战斗设置为: {自动战斗}", 玩家Id, 是否自动战斗);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "设置玩家自动战斗时发生错误");
            await Clients.Caller.SendAsync("自动战斗设置错误", "设置自动战斗时发生错误");
        }
    }

    // 玩家准备就绪
    public async Task 玩家准备就绪(Guid 玩家Id, Guid 战斗Id, bool 准备就绪 = true)
    {
        try
        {
            // 更新玩家战斗状态
            var 玩家状态 = new 玩家战斗状态
            {
                玩家Id = 玩家Id,
                战斗Id = 战斗Id,
                是否准备就绪 = 准备就绪,
                更新时间 = DateTime.Now
            };

            玩家战斗状态列表[玩家Id] = 玩家状态;

            // 更新在线玩家信息
            var 在线玩家 = 在线玩家列表.Values.FirstOrDefault(p => p.玩家角色Id == 玩家Id);
            if (在线玩家 != null)
            {
                在线玩家.是否准备就绪 = 准备就绪;
                var 连接ID = 在线玩家.连接ID;
                if (!string.IsNullOrEmpty(连接ID))
                {
                    在线玩家列表[连接ID] = 在线玩家;
                }
            }

            // 通知所有观察者
            if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
            {
                await Clients.Clients(观察者).SendAsync("玩家准备状态更新", 玩家Id, 准备就绪);
            }

            // 检查是否所有玩家都准备就绪
            if (准备就绪 && 战斗信息列表.TryGetValue(战斗Id, out var 战斗信息))
            {
                var 所有玩家准备就绪 = 战斗信息.玩家列表.All(pId => 
                {
                    return 玩家战斗状态列表.TryGetValue(pId, out var 状态) && 状态.是否准备就绪;
                });

                if (所有玩家准备就绪)
                {
                    // 通知所有观察者开始下一回合
                    if (观察者 != null)
                    {
                        await Clients.Clients(观察者).SendAsync("所有玩家准备就绪", 战斗Id);
                    }
                }
            }

            日志器.LogInformation("玩家 {玩家Id} 准备状态更新: {准备就绪}", 玩家Id, 准备就绪);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "更新玩家准备状态时发生错误");
        }
    }

    // 通知战斗结束
    public async Task 通知战斗结束(Guid 战斗Id, bool 是否胜利, string 结果消息)
    {
        try
        {
            var 消息类型 = 是否胜利 ? "victory" : "defeat";
            await 发送战斗日志(战斗Id, 结果消息, 消息类型);

            // 更新战斗信息
            if (战斗信息列表.TryGetValue(战斗Id, out var 战斗信息))
            {
                战斗信息.战斗状态 = 是否胜利 ? "victory" : "defeat";
                战斗信息.结束时间 = DateTime.Now;
            }

            // 通知所有观察者
            if (战斗观察者列表.TryGetValue(战斗Id, out var 观察者))
            {
                await Clients.Clients(观察者).SendAsync("战斗结果", 结果消息, 是否胜利);
            }

            // 清理战斗观察者
            if (战斗观察者列表.TryRemove(战斗Id, out var 观察者列表))
            {
                foreach (var 连接ID in 观察者列表)
                {
                    await Groups.RemoveFromGroupAsync(连接ID, $"战斗_{战斗Id}");

                    // 更新玩家状态
                    if (在线玩家列表.TryGetValue(连接ID, out var 玩家))
                    {
                        玩家.当前战斗Id = null;
                        在线玩家列表[连接ID] = 玩家;
                    }
                }
            }

            // 清理相关数据
            玩家战斗状态列表.Where(x => x.Value.战斗Id == 战斗Id)
                          .ToList()
                          .ForEach(x => 玩家战斗状态列表.TryRemove(x.Key, out _));

            玩家决策缓存.Where(x => x.Value.战斗Id == 战斗Id)
                      .ToList()
                      .ForEach(x => 玩家决策缓存.TryRemove(x.Key, out _));

            日志器.LogInformation("战斗 {战斗Id} 结束: 胜利={是否胜利}", 战斗Id, 是否胜利);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "通知战斗结束时发生错误");
        }
    }

    // 获取战斗信息
    public async Task 获取战斗信息(Guid 战斗Id)
    {
        try
        {
            if (战斗信息列表.TryGetValue(战斗Id, out var 战斗信息))
            {
                await Clients.Caller.SendAsync("接收战斗信息", 战斗信息);
            }
            else
            {
                await Clients.Caller.SendAsync("接收战斗信息错误", "战斗不存在");
            }
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "获取战斗信息时发生错误");
            await Clients.Caller.SendAsync("接收战斗信息错误", "获取战斗信息时发生错误");
        }
    }

    // 获取战斗单位
    private 战斗单位? 获取战斗单位(Guid 战斗Id, Guid 单位Id)
    {
        if (!战斗信息列表.TryGetValue(战斗Id, out var 战斗信息))
            return null;

        // 在玩家队伍中查找
        var 玩家 = 战斗信息.玩家队伍.FirstOrDefault(p => p.Id == 单位Id);
        if (玩家 != null)
            return 玩家;

        // 在怪物队伍中查找
        var 怪物 = 战斗信息.怪物队伍.FirstOrDefault(m => m.Id == 单位Id);
        return 怪物;
    }

    public async Task 玩家进入战斗(玩家 玩家, 怪物 怪物, Guid 战斗Id)
    {
        try
        {
            // 验证玩家是否在线
            var 在线玩家 = 在线玩家列表.Values.FirstOrDefault(p => p.玩家角色Id == 玩家.Id);
            if (在线玩家 == null)
            {
                日志器.LogWarning("玩家 {玩家名称} 不在线，无法进入战斗", 玩家.名称);
                return;
            }

            // 更新玩家状态
            在线玩家.当前战斗Id = 战斗Id;
            在线玩家.最后活动时间 = DateTime.Now;

            // 加入战斗组
            await Groups.AddToGroupAsync(在线玩家.连接ID, $"战斗_{战斗Id}");

            // 通知客户端进入战斗
            await Clients.Client(在线玩家.连接ID).SendAsync("进入战斗", 战斗Id, 玩家, 怪物);

            日志器.LogInformation("玩家 {玩家名称} 进入战斗 {战斗Id}", 玩家.名称, 战斗Id);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "玩家进入战斗时发生错误");
        }
    }
    #endregion

    #region 管理员功能
    // 推送管理员通知给所有在线玩家
    public async Task 推送管理员通知(string 标题, string 内容, string 类型 = "通知", string 优先级 = "normal")
    {
        try
        {
            var 通知 = new 管理员通知
            {
                标题 = 标题,
                内容 = 内容,
                类型 = 类型,
                优先级 = 优先级,
                时间戳 = DateTime.Now
            };

            // 广播给所有客户端
            await Clients.All.SendAsync("接收管理员通知", 通知);

            日志器.LogInformation("管理员通知: {标题} - {内容}", 标题, 内容);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "推送管理员通知时发生错误");
        }
    }

    // 推送管理员通知给指定玩家
    public async Task 推送管理员通知给玩家(string 玩家名称, string 标题, string 内容, string 类型 = "通知")
    {
        try
        {
            var 通知 = new 管理员通知
            {
                标题 = 标题,
                内容 = 内容,
                类型 = 类型,
                时间戳 = DateTime.Now
            };

            // 查找玩家连接ID
            var 玩家 = 在线玩家列表.Values.FirstOrDefault(p => p.玩家名称 == 玩家名称);
            if (玩家 != null)
            {
                await Clients.Client(玩家.连接ID).SendAsync("接收管理员通知", 通知);
                日志器.LogInformation("发送管理员通知给玩家 {玩家名称}: {标题}", 玩家名称, 标题);
            }
            else
            {
                日志器.LogWarning("找不到玩家 {玩家名称} 发送管理员通知", 玩家名称);
            }
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "推送管理员通知给玩家时发生错误");
        }
    }

    // 获取服务器状态
    public async Task 获取服务器状态()
    {
        try
        {
            var 状态 = new
            {
                在线玩家数 = 在线玩家列表.Count,
                进行中战斗数 = 战斗信息列表.Count(x => x.Value.战斗状态 == "active"),
                总战斗数 = 战斗信息列表.Count,
                服务器启动时间 = DateTime.Now.AddHours(-1), // 示例时间
                当前时间 = DateTime.Now
            };

            await Clients.Caller.SendAsync("接收服务器状态", 状态);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "获取服务器状态时发生错误");
        }
    }
    #endregion

    #region 辅助方法
    private async Task 发送在线玩家列表()
    {
        try
        {
            var 在线玩家 = 在线玩家列表.Values.ToList();
            await Clients.All.SendAsync("接收在线玩家列表", 在线玩家);
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "发送在线玩家列表时发生错误");
        }
    }

    private string? 获取玩家连接ID(Guid 玩家Id)
    {
        return 在线玩家列表.Values.FirstOrDefault(p => p.玩家角色Id == 玩家Id)?.连接ID;
    }

    private string 获取玩家名称(Guid 玩家Id)
    {
        return 在线玩家列表.Values.FirstOrDefault(p => p.玩家角色Id == 玩家Id)?.玩家名称 ?? "未知玩家";
    }

    private bool 验证玩家在战斗中(Guid 玩家Id, Guid 战斗Id)
    {
        var 连接ID = 获取玩家连接ID(玩家Id);
        if (连接ID == null) return false;

        return 在线玩家列表.TryGetValue(连接ID, out var 玩家) &&
              玩家.当前战斗Id == 战斗Id;
    }

    private List<object> 获取小队成员信息(string 小队ID)
    {
        var 成员信息 = new List<object>();

        if (小队成员列表.TryGetValue(小队ID, out var 成员列表))
        {
            foreach (var 连接ID in 成员列表)
            {
                if (在线玩家列表.TryGetValue(连接ID, out var 玩家))
                {
                    成员信息.Add(new
                    {
                        玩家.玩家名称,
                        玩家.当前位置,
                        玩家.登录时间
                    });
                }
            }
        }

        return 成员信息;
    }

    // 清理过期数据（可以由定时任务调用）
    public void 清理过期数据()
    {
        try
        {
            var 当前时间 = DateTime.Now;

            // 清理长时间未活动的玩家
            var 过期玩家 = 在线玩家列表.Where(p =>
                (当前时间 - p.Value.最后活动时间).TotalMinutes > 30).ToList();

            foreach (var 玩家 in 过期玩家)
            {
                在线玩家列表.TryRemove(玩家.Key, out _);
                日志器.LogInformation("清理过期玩家: {玩家名称}", 玩家.Value.玩家名称);
            }

            // 清理已结束的战斗
            var 结束战斗 = 战斗信息列表.Where(b =>
                b.Value.结束时间.HasValue &&
                (当前时间 - b.Value.结束时间.Value).TotalHours > 1).ToList();

            foreach (var 战斗 in 结束战斗)
            {
                战斗信息列表.TryRemove(战斗.Key, out _);
                日志器.LogInformation("清理结束战斗: {战斗Id}", 战斗.Key);
            }

            // 清理过期的决策缓存
            var 过期决策 = 玩家决策缓存.Where(d =>
                (当前时间 - d.Value.提交时间).TotalMinutes > 5).ToList();

            foreach (var 决策 in 过期决策)
            {
                玩家决策缓存.TryRemove(决策.Key, out _);
            }
        }
        catch (Exception ex)
        {
            日志器.LogError(ex, "清理过期数据时发生错误");
        }
    }
    #endregion
}
